#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <mpi.h>

typedef struct timeval timeVal;

long calcRuntime(timeVal *begin, timeVal *end);

void initVector(long* vector,unsigned size);


int main(int argc, char** argv){
	int retVal = 0;
		
	int mpi_rank;	
	int signal;

	MPI_Status status;

	timeVal start, end;
	long *message = NULL;
	unsigned messageSize = 0; 
	long rtt = 0;
	MPI_Init(&argc,&argv);

	if(argc >= 2){
		messageSize = atoi(argv[1]);
	}else{
		printf("Missing Arguments:\n Usage ./ex03_2 <Message Size(byte)>");
		retVal = -1;
	}

	if(retVal == 0){

		MPI_Comm_rank(MPI_COMM_WORLD,&mpi_rank);

		messageSize = messageSize / sizeof(long);
		message = (long*)malloc(messageSize*sizeof(long));

		if(mpi_rank == 0){
			initVector(message,messageSize);

			gettimeofday(&start,NULL);

			MPI_Send(message,messageSize,MPI_LONG,1,0,MPI_COMM_WORLD);
			MPI_Recv(message,messageSize,MPI_LONG,1,0,MPI_COMM_WORLD,&status);	

			gettimeofday(&end,NULL);
			rtt = calcRuntime(&start,&end);

			printf("Rank: %d Startval: %ld.%ld Endval: %ld.%ld Messagesize[kB]: %ld RTT: %ld\n",mpi_rank,start.tv_sec,start.tv_usec,end.tv_sec,end.tv_usec,(messageSize*sizeof(long))/1024,rtt);	
		}else if(mpi_rank == 1){
			MPI_Recv(message,messageSize,MPI_LONG,0,0,MPI_COMM_WORLD,&status);
			//gettimeofday(&end,NULL);
			MPI_Send(message,messageSize,MPI_LONG,0,0,MPI_COMM_WORLD);
		}
	}

	if(message != NULL){
		free(message);
	}

	MPI_Finalize();
	
	return retVal;
}

/*Function: calcRuntime() */
long calcRuntime(timeVal *begin, timeVal *end){
	timeVal diff;

	diff.tv_sec = end->tv_sec - begin->tv_sec;

	if(begin->tv_usec > end->tv_usec){
		diff.tv_usec = (1e6 - end->tv_usec) + begin->tv_usec;
	}else{
		diff.tv_usec = end->tv_usec - begin->tv_usec;
	}

	return (diff.tv_sec * 1e6 + diff.tv_usec);
}

/*Function: initVector() */
void initVector(long* vector,unsigned size){
	unsigned i = 0;

	for(i = 0; i < size; i++){
		vector[i] = 0;
	}
}
